package com.app.model 
{
	import flash.utils.Timer;
	
	import flash.events.Event;
	import flash.events.DataEvent;
	import flash.events.TimerEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	
	import com.adobe.crypto.MD5;
	import com.adobe.serialization.json.JSON;
	
	import org.puremvc.as3.patterns.proxy.Proxy;
	import org.puremvc.as3.interfaces.IProxy;
	
	import com.app.AppFacade;

	import com.peachcastle.socket.PClient;
	
	import com.peachcastle.debug.Log;
	
	/**
	 * ...
	 * @author kevin
	 */
	public class RoomConnProxy extends Proxy implements IProxy
	{
		public static const NAME:String = 'RoomConnProxy';
		
		private static const INT_TYPE:Array = ['mid', 'type', 'chips', 'sit_chips', 'runtime_status', 
												'is_banker', 'time', 'b_exp', 'u_exp'];
		
		public static const STAT_WAIT_START:int 	= 0;
		public static const STAT_WAIT_BASE_POUR:int = 1;
		public static const STAT_WAIT_CALL_POUR:int = 2;
		public static const STAT_WAIT_PK:int 		= 3;
		
		private var _client:PClient = null;
		
		//timer
		private var _interval_val:uint = 200000;
		private var _timer:Timer = null;
		
		private var _mid:int = 0;
		private var _rid:int = 0;
		
		private var _receiveCmd:int = 0;
		
		private var _isConn:Boolean = false;
		
		public function RoomConnProxy() 
		{
			super(NAME);
		}
		
		public function connect(ip:String, port:Number, mid:int, rid:int):void
		{
			Log.info("room connect... ip = " + ip + " port = " + port);
			
			_mid = mid;
			_rid = rid;
			
			var p : Object = {
				protocol		: 'Muduo', 
				addr			: ip, 
				port			: port, 
				on_connect		: roomOnConnect, 
				on_close		: roomOnClose, 
				on_cmd			: roomOnCmd
			};
			
			_client = new PClient(p);
		}
		
		public function close():void
		{
			if (_isConn) 
			{
				_client.socketClose();
				_isConn = false;
			}
		}
		
		private function roomOnConnect():void
		{
			_isConn = true;
			
			sendNotification(AppFacade.READY_ENTER_ROOM);
			
			addTimer();
		}
		
		private function addTimer():void
		{
			// Connected, start timer
			if (!this._timer)
			{
				this._timer = new Timer(this._interval_val);
			}
			
			if (!this._timer.hasEventListener(TimerEvent.TIMER))
			{
				this._timer.addEventListener(TimerEvent.TIMER, hbHandler);
			}
			
			this._timer.start();
		}
		
		private function stopTimer():void
		{
			if (this._timer)
			{
				this._timer.stop();
			}
		}
		
		private function hbHandler(e:TimerEvent = null):void
		{
			sendData('heartbeat', {mid: _mid, rid: _rid});
		}
		
		public function sendData(cmd:String, data:Object = null):void
		{
			if (!_isConn)
			{
				sendNotification(AppFacade.CLIENT_NOTICE, ['error_100']);
				return;
			}

			switch(cmd)
			{
				case "enter_room":
					data["cmd_id"] = CMD_ENTER_ROOM_REQ;
				
					break;
					
				case "sit_down":
					data["cmd_id"] = CMD_SIT_DOWN_REQ;
					
					break;
					
				case "sit_up":
					data["cmd_id"] = CMD_STAND_UP_REQ;
					
					break;
					
				case "go_hall":
					data["cmd_id"] = CMD_GO_HALL_REQ;
					
					break;
					
				case 'start_game':
					data["cmd_id"] = CMD_START_GAME_REQ;
					
					break;
					
				case 'add_base_pour':
					data["cmd_id"] = CMD_ADD_BASE_POUR_REQ;
					
					break;
					
				case 'call_pour':
					data["cmd_id"] = CMD_CALL_POUR_REQ;
					
					break;
					
				case 'start_pk':
					data["cmd_id"] = CMD_PK_REQ;
					
					break;
					
				case 'chat':
					data["cmd_id"] = CMD_CHAT_REQ;
				
					break;
					
				case 'expression':
					data["cmd_id"] = CMD_EXPRESSION_REQ;
				
					break;
					
				case 'heartbeat':
					data["cmd_id"] = CMD_HEARTBEAT_REQ;
				
					break;
			}
			data.mid = _mid;
			data.rid = _rid;
			
			var len:int = _client.send(data);
			
			Log.info("room send data ====== : cmd = " + cmd, data);
		}
		
		private function roomOnCmd(cmd:Object):void
		{
			_receiveCmd = cmd.params.cmd_id;

			if (cmd.params['err'] > 0)
			{
				sendNotification(AppFacade.SERVER_NOTICE, [cmd.params['err']]);
				
				return;
			}
			
			if (cmd.params.hasOwnProperty('err')) delete cmd.params['err'];
			if (cmd.params.hasOwnProperty('msg')) delete cmd.params['msg'];
			if (cmd.params.hasOwnProperty('cmd_id')) delete cmd.params['cmd_id'];
			
			
			for (var key:String in cmd.params)
			{
				if (INT_TYPE.indexOf(key) != -1 && typeof(cmd.params[key]) == 'string')
				{
					cmd.params[key] = int(cmd.params[key]);
				}
			}
			
			Log.info("room receve data ====== : cmd = " + _receiveCmd, cmd.params);
			
			switch (_receiveCmd)
			{
				case CMD_ENTER_ROOM_RES:
					enterRoom(cmd.params);
					
					break;
					
				case CMD_SIT_DOWN_RES:
					sitDown(cmd.params);
					
					break;
					
				case CMD_STAND_UP_RES:
					stand(cmd.params);
					
					break;
					
				case CMD_GO_HALL_RES:
					goHall(cmd.params);
					
					break;
					
				case CMD_START_GAME_RES:
					startGame(cmd.params);
					
					break;
					
				case CMD_ADD_BASE_POUR_RES:
					addBasePour(cmd.params);
					
					break;
					
				case CMD_END_BASE_POUR_RES:
					startCallPour(cmd.params);
					
					break;
					
				case CMD_CALL_POUR_RES:
					callPour(cmd.params);
					
					break;
					
				case CMD_END_CALL_POUR_RES:
					startPk(cmd.params);
					
					break;
					
				case CMD_PK_RES:
					pkResult(cmd.params);
					
					break;
					
				case CMD_GAME_OVE_RES:
					gameOver();
					
					break;
					
				case CMD_EXP_ADD_RES:
					expAdd(cmd.params);
				
					break;	
					
				case CMD_CHAT_RES:
					sendNotification(AppFacade.CHAT, [cmd.params]);
					
					break;
					
				case CMD_EXPRESSION_RES:
					sendNotification(AppFacade.EXPRESSION, [cmd.params]);
				
					break;
					
				case CMD_HEARTBEAT_RES:
					heartbeatClose(cmd.params);
				
					break;
			}
		}
		
		private function enterRoom(data:Object):void
		{
			sendNotification(AppFacade.ENTER_ROOM, [data]);
		}
		
		private function sitDown(data:Object):void
		{
			sendNotification(AppFacade.SIT_DOWN, [data]);
		}
		
		private function stand(data:Object):void
		{
			sendNotification(AppFacade.STAND, [data]);
		}
		
		private function goHall(data:Object):void
		{
			sendNotification(AppFacade.GO_HALL, [data]);
		}
		
		private function startGame(data:Object):void
		{
			sendNotification(AppFacade.START_GAME, [data]);
		}
		
		private function addBasePour(data:Object):void
		{
			sendNotification(AppFacade.ADD_BASE_POUR, [data]);
		}
		
		private function startCallPour(data:Object):void
		{
			sendNotification(AppFacade.CALL_POUR_START, [data]);
		}
		
		private function callPour(data:Object):void
		{
			sendNotification(AppFacade.CALL_POUR, [data]);
		}
		
		private function startPk(data:Object):void
		{
			sendNotification(AppFacade.START_PK, [data]);
		}
		
		private function pkResult(data:Object):void
		{
			sendNotification(AppFacade.PK_RESULT, [data]);
		}
		
		private function gameOver():void
		{
			sendNotification(AppFacade.GAME_OVER);
		}
		
		private function expAdd(data:Object):void
		{
			sendNotification(AppFacade.EXP_ADD, [data]);
		}
		
		private function heartbeatClose(data:Object):void
		{
			sendNotification(AppFacade.HEARTBAET_USER_CLOSE, [data.mids]);
		}
		
		private function roomOnClose():void
		{
			_isConn = false;
			sendNotification(AppFacade.CLIENT_NOTICE, ['error_100']);
			Log.info("roomOnClose...");
		}
		
		///////////////
		////error
		//////////////
		private function ioErrorHandler(e:IOErrorEvent):void
		{
			_isConn = false;
			sendNotification(AppFacade.CLIENT_NOTICE, ['error_100']);
			Log.info("Room IOErrorEvent...");
		}
		
		private function securityErrorHandler(e:SecurityErrorEvent):void
		{
			_isConn = false;
			sendNotification(AppFacade.CLIENT_NOTICE, ['error_100']);
			Log.info("Room SecurityErrorEvent...");
		}
	}

}
include "./socket/CMD.as"